#include <tinyhal.h>

//--//


#define FLASH_MANUFACTURER_CODE              0x0000  // not used
#define FLASH_DEVICE_CODE                    0x0000  // not used
#define FLASH_MEMORY_BASE                    FLASH_MEMORY_Base	// Don't forget to set!
#define FLASH_BLOCK_COUNT                    256
#define FLASH_BYTES_PER_BLOCK                2048
#define FLASH_BYTES_PER_SECTOR               2
#define FLASH_BLOCK_ERASE_TYPICAL_TIME_USEC  1000000 // not used
#define FLASH_SECTOR_WRITE_TYPICAL_TIME_USEC 10      // not used
#define FLASH_BLOCK_ERASE_MAX_TIME_USEC      4000000 // not used
#define FLASH_SECTOR_WRITE_MAX_TIME_USEC     100     // not used
#define FLASH_BLOCK_ERASE_ACTUAL_TIME_USEC   10000   // not used

//--//

// EBIU Information

#define FM3__CHIP_SELECT       0
#define FM3__WAIT_STATES       5 // not used
#define FM3__RELEASE_COUNTS    0
#define FM3__BIT_WIDTH         16
#define FM3__BASE_ADDRESS      FLASH_MEMORY_BASE
#define FM3__SIZE_IN_BYTES     FLASH_BLOCK_COUNT * FLASH_BYTES_PER_BLOCK
#define FM3__WP_GPIO_PIN       GPIO_PIN_NONE
#define FM3__WP_ACTIVE         FALSE



//--//



// BlockDeviceInformation

#define FM3__IS_REMOVABLE      FALSE
#define FM3__SUPPORTS_XIP      TRUE
#define FM3__WRITE_PROTECTED   FALSE
#define FM3__SUPP_COPY_BACK    FALSE
#define FM3__NUM_REGIONS       3

//#define BYTES_PER_SECTOR					16384
#define REGION1_XIP_ADDRESS					FLASH_MEMORY_BASE
#define REGION1_BYTES_PER_BLK				0x4000
#define REGION1_NUM_OF_BLOCKS				2

#define REGION2_XIP_ADDRESS					REGION1_XIP_ADDRESS + (REGION1_BYTES_PER_BLK * REGION1_NUM_OF_BLOCKS)
#define REGION2_BYTES_PER_BLK				0x18000
#define REGION2_NUM_OF_BLOCKS				1

#define REGION3_XIP_ADDRESS					REGION2_XIP_ADDRESS + (REGION2_BYTES_PER_BLK * REGION2_NUM_OF_BLOCKS)
#define REGION3_BYTES_PER_BLK				0x20000
#define REGION3_NUM_OF_BLOCKS				3

//--//


const BlockRange g_FM3_BlockRange1[] =
{
	{ BlockRange::BLOCKTYPE_CODE      ,   0,   1 }		// 00000000 CLR			32k
};

const BlockRange g_FM3_BlockRange2[] =
{
	{ BlockRange::BLOCKTYPE_CODE      ,   0,   0 }		// 00008000 CLR			96k
};

const BlockRange g_FM3_BlockRange3[] =
{
	{ BlockRange::BLOCKTYPE_CODE      ,   0,   1 },		// 00020000 CLR			256k
	{ BlockRange::BLOCKTYPE_DEPLOYMENT,   2,   2 }		// 00060000 Deployment	128k
};

const BlockRegionInfo  g_FM3_BlkRegion[FM3__NUM_REGIONS] =
{
    {
    	REGION1_XIP_ADDRESS,		// ByteAddress   Start;           // Starting Sector address
    	REGION1_NUM_OF_BLOCKS,		// UINT32        NumBlocks;       // total number of blocks in this region
    	REGION1_BYTES_PER_BLK,		// UINT32        BytesPerBlock;   // Total number of bytes per block
        ARRAYSIZE_CONST_EXPR(g_FM3_BlockRange1),
        g_FM3_BlockRange1,
    },
    {
    	REGION2_XIP_ADDRESS,		// ByteAddress   Start;           // Starting Sector address
    	REGION2_NUM_OF_BLOCKS,		// UINT32        NumBlocks;       // total number of blocks in this region
    	REGION2_BYTES_PER_BLK,		// UINT32        BytesPerBlock;   // Total number of bytes per block
        ARRAYSIZE_CONST_EXPR(g_FM3_BlockRange2),
        g_FM3_BlockRange2,
    },
    {
    	REGION3_XIP_ADDRESS,		// ByteAddress   Start;           // Starting Sector address
    	REGION3_NUM_OF_BLOCKS,		// UINT32        NumBlocks;       // total number of blocks in this region
    	REGION3_BYTES_PER_BLK,		// UINT32        BytesPerBlock;   // Total number of bytes per block
        ARRAYSIZE_CONST_EXPR(g_FM3_BlockRange3),
        g_FM3_BlockRange3,
    }
};


//--//

#undef MEMORY_BLOCKTYPE_GCC_SPECIAL_CODE 

//--//


const BlockDeviceInfo g_FM3_DeviceInfo=
{
    {  
        FM3__IS_REMOVABLE,               // BOOL Removable;
        FM3__SUPPORTS_XIP,               // BOOL SupportsXIP;
        FM3__WRITE_PROTECTED,            // BOOL WriteProtected;
        FM3__SUPP_COPY_BACK              // BOOL SupportsCopyBack
    },
    FLASH_SECTOR_WRITE_TYPICAL_TIME_USEC,  // UINT32 MaxSectorWrite_uSec;
    FLASH_BLOCK_ERASE_ACTUAL_TIME_USEC,    // UINT32 MaxBlockErase_uSec;
    FLASH_BYTES_PER_SECTOR,                // UINT32 BytesPerSector;     

    FLASH_MEMORY_Size,                     // UINT32 Size;

    FM3__NUM_REGIONS,                    // UINT32 NumRegions;
    g_FM3_BlkRegion,                     // const BlockRegionInfo* pRegions;
};


struct MEMORY_MAPPED_NOR_BLOCK_CONFIG g_FM3_BS_Config =
{
    { // BLOCK_CONFIG
        {
            FM3__WP_GPIO_PIN,            // GPIO_PIN             Pin;
            FM3__WP_ACTIVE,              // BOOL                 ActiveState;
        },

        &g_FM3_DeviceInfo,               // BlockDeviceinfo
    },

    { // CPU_MEMORY_CONFIG
        FM3__CHIP_SELECT,                // UINT8  CPU_MEMORY_CONFIG::ChipSelect;
        TRUE,                              // UINT8  CPU_MEMORY_CONFIG::ReadOnly;
        FM3__WAIT_STATES,                // UINT32 CPU_MEMORY_CONFIG::WaitStates;
        FM3__RELEASE_COUNTS,             // UINT32 CPU_MEMORY_CONFIG::ReleaseCounts;
        FM3__BIT_WIDTH,                  // UINT32 CPU_MEMORY_CONFIG::BitWidth;
        FM3__BASE_ADDRESS,               // UINT32 CPU_MEMORY_CONFIG::BaseAddress;
        FM3__SIZE_IN_BYTES,              // UINT32 CPU_MEMORY_CONFIG::SizeInBytes;
        0,                                 // UINT8  CPU_MEMORY_CONFIG::XREADYEnable 
        0,                                 // UINT8  CPU_MEMORY_CONFIG::ByteSignalsForRead 
        0,                                 // UINT8  CPU_MEMORY_CONFIG::ExternalBufferEnable
    },

    0,                                     // UINT32 ChipProtection;
    FLASH_MANUFACTURER_CODE,               // UINT32 ManufacturerCode;
    FLASH_DEVICE_CODE,                     // UINT32 DeviceCode;
};

//--//


#if defined(ADS_LINKER_BUG__NOT_ALL_UNUSED_VARIABLES_ARE_REMOVED)
#pragma arm section rodata = "g_FM3_BS"
#endif

struct BlockStorageDevice g_FM3_BS;

#if defined(ADS_LINKER_BUG__NOT_ALL_UNUSED_VARIABLES_ARE_REMOVED)
#pragma arm section rodata 
#endif 

//--//

